﻿// E-Book Copier
// Copyright (C) 2009 Chuan-Gen Fan
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// Project: http://code.google.com/p/ebookcopier/
// Contact Author:
//    website: http://chuangen.name/
// e-mail/msn: chuangen@live.cn

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace EbookCopier
{
    /// <summary>
    /// 获取指向由指定枚举标识的系统特殊文件夹的路径。
    /// </summary>
    /// <remarks>.NET2.0中的 Environment.GetFolderPath 方法无法获取如“Fonts”等文件夹。所以设计此类以支持更多的文件夹。</remarks>
    internal class SpecialFolders
    {
        // C# representation of the IMalloc interface.
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
           Guid("00000002-0000-0000-C000-000000000046")]
        interface IMalloc
        {
            [PreserveSig]
            IntPtr Alloc([In] int cb);
            [PreserveSig]
            IntPtr Realloc([In] IntPtr pv, [In] int cb);
            [PreserveSig]
            void Free([In] IntPtr pv);
            [PreserveSig]
            int GetSize([In] IntPtr pv);
            [PreserveSig]
            int DidAlloc(IntPtr pv);
            [PreserveSig]
            void HeapMinimize();
        }

        [DllImport("Shell32.DLL")]
        static extern int SHGetMalloc(out IMalloc ppMalloc);

        [DllImport("Shell32.DLL")]
        static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, int nFolder, out IntPtr ppidl);

        [DllImport("Shell32.DLL")]
        static extern int SHGetPathFromIDList(IntPtr pidl, StringBuilder Path);




        private static readonly int MAX_PATH = 260;
        /// <summary>
        /// Helper function that returns the IMalloc interface used by the shell.
        /// </summary>
        private static IMalloc GetSHMalloc()
        {
            IMalloc malloc;
            SHGetMalloc(out malloc);
            return malloc;
        }

        /// <summary>
        /// 获取字体文件夹。
        /// </summary>
        public static string Fonts
        {
            get { return GetPath(IntPtr.Zero, SpecialFolderID.FONTS); }
        }

        /// <summary>
        /// 获取指定的系统文件夹。
        /// GetSpecialPath
        /// Shows the folder browser dialog box with the specified owner window.
        /// </summary>
        /// <param name="hWndOwner">父窗体句柄</param>
        /// <param name="folderId">CSIDL</param>
        /// <returns></returns>
        public static string GetPath(IntPtr hWndOwner, SpecialFolderID folderId)
        {
            string directoryPath = null;
            IntPtr pidlRoot = IntPtr.Zero;

            // Get the IDL for the specific startLocation.
            SHGetSpecialFolderLocation(hWndOwner, (int)folderId, out pidlRoot);

            if (pidlRoot == IntPtr.Zero)
            {
                return null;
            }

            try
            {
                // Then retrieve the path from the IDList.
                StringBuilder sb = new StringBuilder(MAX_PATH);
                if (0 == SHGetPathFromIDList(pidlRoot, sb))
                {
                    return null;
                }

                // Convert to a string.
                directoryPath = sb.ToString();
            }
            finally
            {
                IMalloc malloc = GetSHMalloc();
                malloc.Free(pidlRoot);
            }

            return directoryPath;
        }

    }

}
